package com.tn.service.cardrobot.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.SystemClock;
import cn.hutool.core.util.StrUtil;
import com.gitee.hifong45.FE;
import com.gitee.hifong45.Kv;
import com.gitee.hifong45.Msg;
import com.tn.controller.alarm.common.model.cardrobot.CardSenderRobotInfoDO;
import com.tn.dao.cardsender.CardSenderRobotDao;
import com.tn.service.cardrobot.CardSendRobotService;
import com.tn.socket.CardSendRobot;
import com.tn.socket.SocketPoolRunner;
import com.tn.tcp.CardMachine;
import com.tn.tcp.CardMachineInData;
import com.tn.utils.SocketParamUtil;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @ClassName CardSendRobotServiceImpl
 * @Description TODO
 * @Author Yezhongzhu
 * @Date 2022/1/10 14:49
 * @Version v1.0
 **/
@Service
@Slf4j
public class CardSendRobotServiceImpl implements CardSendRobotService {
    @Autowired
    private CardSenderRobotDao cardSenderRobotDao;
    @Autowired
    private SocketPoolRunner runner;

    private static final int SLOT_SIZE = 9;

    @Override
    public List<CardSenderRobotInfoDO> queryCardRobotList() {
        return cardSenderRobotDao.queryCardRobotList();
    }

    @Override
    public void popupAllCard(int id, String stationId) {
        for(CardSendRobot cardSendRobot: runner.clients){
            if(stationId.equals(cardSendRobot.getSTATIONID())){
                for(int i = 1;i<=SLOT_SIZE;i++){
                    String packageData = SocketParamUtil.buildPopupCardParam(i);
                    cardSendRobot.send(packageData);
                }
            }
        }
    }

    // 读取发卡机实时状态信息：槽位、集卡、电量
    public Kv getCarMachineInfo(String stationId, Boolean allInfo) {
        if(StrUtil.isNotBlank(stationId)) {
            if(!CardMachineInData.cardMachineMap.containsKey(stationId)) {
                return Kv.of("size", 0);
            }
            return Kv.of("size", 1,  "cardMachine", Kv.of(stationId, CardMachineInData.cardMachineMap.get(stationId)));
        }
        return Kv.of("size", CardMachineInData.cardMachineMap.size(), "cardMachine", CardMachineInData.cardMachineMap);
    }

    // 弹出指定发卡机的指定/随机槽位的集卡
    public String popCard(String stationId, String slot) {
        CardMachine cm = CardMachineInData.cardMachineMap.get(stationId);
        FE.nullThrow(cm, "该发卡机未登录/无信息");
        FE.trueThrow(cm.getUsableSlotCard() == null || cm.getUsableSlotCard().isEmpty(), Msg.NOT_FOUND, "该发卡机无可用卡");

        log.info("准备弹出{} - {} 的集卡", stationId, slot);
        String cardId = CardMachineInData.popCardGetCardId1(cm, slot);
        return cardId;

    }

    // 让指定模组弹出所有卡
    public Kv popAllCard(String stationId) {
        CardMachine cm = CardMachineInData.cardMachineMap.get(stationId);
        if(cm == null || cm.getUsableSlotCard() == null || cm.getUsableSlotCard().isEmpty()) {
            return Kv.of("all", "success");
        }
        int num = 5;
        log.info("{} 开始，模组全弹卡 {}，最多进行 {} 次循环", DateUtil.now(), stationId, num);
        var slotCards = cm.getUsableSlotCard(); // key = slot
        int allSize = slotCards.size(); // 开始时可用卡数
        var btime = SystemClock.now(); // 开始时间

        for(num = 5; num >0; num --) {
            slotCards = cm.getUsableSlotCard();
            log.info("{} 第{} 次： 当前共有 {} 个可用卡: {}", stationId, 5-num, slotCards.size(), slotCards.keySet());
            var it = slotCards.entrySet().iterator();
            while(it.hasNext()) {
                var item = it.next();
                var slot = item.getKey();
                var cardId = CardMachineInData.popCardGetCardIdNoRemove(cm, slot);
                if(StrUtil.isNotBlank(cardId)) {
                    it = slotCards.entrySet().iterator();
                }
            }
        }
        var etime = SystemClock.now(); // 结束时间
        var difftime = etime - btime; // 耗时
        var ret = Kv.of("all", "failed", "usedTime", difftime, "allCounts", allSize, "restCounts", slotCards.size());

        if(slotCards.size() > 0) {
            ret.put("slotCards", slotCards);
        } else {
            ret.put("all", "success-pop");
        }

        log.info("{} 结束，模组全弹卡 {}，耗时 {}ms. 共{}，弹出{}，剩余{}",
                DateUtil.now(), stationId, difftime, allSize, allSize - slotCards.size(), slotCards.size());
        log.info("{}", ret);
        return ret;
    }
}
